from flask_sqlalchemy import SQLAlchemy
from BookWorldWeb.extensions import bcrypt

db = SQLAlchemy()

tags = db.Table('post_tags', db.Column('post_id', db.Integer(), db.ForeignKey('post.id')),
                db.Column("tag_id", db.Integer(), db.ForeignKey('tag.id')))


class User(db.Model):
    """
    用户
    """
    # 自定义表名
    __table_name__ = 'user'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(255))
    password = db.Column(db.String(255))
    posts = db.relationship(
        'Post',
        backref='user',
        # backref参数可以使我们通过Post.user属性对于User对象进行读取和修改.
        # 例如: second_post = Post('Second Title')
        # second_post.user = user
        # db.session.add(second_post)
        # db.session.commit()
        # 由于user.posts是一个列表, 所以我们也可以通过把Post对象直接添加进这个列表,
        # 来自动保存它:
        # second_post = Post('Second Title')
        # user.posts.append(second_post)
        # db.session.add(user)
        # db.session.commit()
        # 由于backref被设置为动态方式,所以我们既可以把这个关联字段看做列表,
        # 也可以把他看作一个查询对象:
        # user.ports.order_by(Post.publish_date.desc()).all()
        lazy='dynamic'
        # lazy参数会告诉SQLAlchemy如何去加载我们指定的关联对象.
        # 如果设为子查询方式(subquery), 则会在加载完Post对象的时候, 就立即加载与
        # 其相关联的对象. 这样会让总查询数量减少, 但如果返回的条目数量很多, 就会比较慢.
        # 另外, 也可以设置为动态方式(dynamic), 这样关联对象会在被使用的时候在进行
        # 加载, 并且在返回前进行过滤. 如果返回的对象很多, 或者未来会变得很多, 那最好采用
        # 这种方式.
    )

    # 不是必须定义, 如果没有定义则Flask会自动创建全属性的__init__
    def __init__(self, username):
        self.username = username

    # 不是必须定义
    def __repr__(self):
        return "<User '{}'>".format(self.username)

    def set_password(self, password):
        """
        密码加密
        :param password: 密码
        :return: 加密后的密码
        """
        self.password = bcrypt.generate_password_hash(password)

    def check_password(self, password):
        """
        检查密码正确性
        :param password: 密码
        :return: 是否正确
        """
        return bcrypt.check_password_hash(self.password, password)


class Post(db.Model):
    """
    文章
    """
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(255))
    text = db.Column(db.Text())
    publish_date = db.Column(db.DateTime())
    comments = db.relationship(
        'Comment',
        backref='post',
        lazy='dynamic'
    )
    tags = db.relationship(
        'Tag',
        secondary=tags,
        backref=db.backref('posts', lazy='dynamic')
    )
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))  # user使用的是表名__table_name__ = 'user'

    def __init__(self, title):
        self.title = title

    def __repr__(self):
        return "<Post '{}'>".format(self.title)


class Comment(db.Model):
    """
    评论
    """
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(255))
    text = db.Column(db.Text())
    date = db.Column(db.DateTime())
    post_id = db.Column(db.Integer(), db.ForeignKey('post.id'))

    def __repr__(self):
        return "<Comment '{}'>".formate(self.text[:15])


class Tag(db.Model):
    """
    标签
    """
    id = db.Column(db.Integer(), primary_key=True)
    title = db.Column(db.String(255))

    def __init__(self, title):
        self.title = title

    def __repr__(self):
        return "<Tag '{}'>".format(self.title)
